# app/ui/main_window.py - 主窗口UI类
import cv2
from PySide6.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QVBoxLayout
from PySide6.QtCore import Qt, QTimer
import os

from app.ui.components import VideoPanel, ValvePanel, ControlPanel
from app.detection import ObjectDetector
from app.config import DEFAULT_REGION, DEFAULT_MODEL_PATH, DEFAULT_CONF
from app.audio.tts import TextToSpeech
from app.plc import PLCClient
from .components.ip_dialog import IPInputDialog

class ObjectDetectionWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("物体检测计数器")
        self.setGeometry(100, 100, 1200, 800)

        # 初始化语音引擎
        self.tts_engine = TextToSpeech()

        # 初始化变量
        self.video_path = None
        self.cap = None
        self.is_processing = False
        self.timer = QTimer()
        self.timer.timeout.connect(self._process_frame)
        
        # 初始化检测器
        self.detector = ObjectDetector(
            region_points=DEFAULT_REGION,
            model_path=DEFAULT_MODEL_PATH,
            conf=DEFAULT_CONF
        )
        
        # 初始化语音播报定时器
        self.speech_timer = QTimer()
        self.speech_timer.timeout.connect(self.speak_results)

        # 初始化PLC客户端
        self.plc_client = PLCClient('192.168.0.20')
        if self.plc_client.connect():
            self.plc_client.io_state_changed.connect(self._handle_io_state_change)
            self.plc_client.start_monitoring()
        
        # 创建UI组件
        self._setup_ui()
        
        # 加载蝶阀图片
        self.valve_panel.load_valve_image("蝶阀开.png")
        
        # 连接信号和槽
        self._connect_signals()
        
    def _setup_ui(self):
        # 创建主窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局，使用水平布局放置主视频区域和蝶阀图片区域
        main_horizontal_layout = QHBoxLayout(central_widget)
        main_horizontal_layout.setContentsMargins(5, 5, 5, 5)  # 减小边距
        
        # 主视频和控制区域容器
        main_content_widget = QWidget()
        main_layout = QVBoxLayout(main_content_widget)
        main_layout.setContentsMargins(0, 0, 0, 0)  # 移除内边距
        main_layout.setSpacing(5)  # 减小组件间距
        
        # 创建视频面板
        self.video_panel = VideoPanel()
        main_layout.addWidget(self.video_panel, 95)  # 分配95%的垂直空间给视频区域
        
        # 创建控制面板
        self.control_panel = ControlPanel(self.tts_engine)
        main_layout.addWidget(self.control_panel, 5)  # 只分配5%的垂直空间给控制面板
        
        # 创建蝶阀面板
        self.valve_panel = ValvePanel()
        
        # 添加主内容区域和蝶阀区域到水平布局
        main_horizontal_layout.addWidget(main_content_widget, 9)  # 分配90%的空间
        main_horizontal_layout.addWidget(self.valve_panel, 1)     # 分配10%的空间
        
    def _connect_signals(self):
        """连接所有信号和槽"""
        self.control_panel.open_video_button.clicked.connect(self.open_video)
        self.control_panel.start_button.clicked.connect(self.toggle_processing)
        self.control_panel.tts_button.clicked.connect(self.speak_results)
        self.control_panel.auto_speech_button.clicked.connect(self.toggle_auto_speech)
        self.control_panel.connect_raspberry_button.clicked.connect(self.connect_raspberry_pi)
        
    def open_video(self):
        file_path = self.control_panel.open_video_dialog()
        
        if file_path:
            self.video_path = file_path
            self.control_panel.start_button.setEnabled(True)
            self.video_panel.set_status_message(f"已选择视频: {file_path}")
            
    def toggle_auto_speech(self):
        """切换自动语音播报功能"""
        self.auto_speech_enabled = self.control_panel.toggle_auto_speech()
        
        if self.auto_speech_enabled:
            # 启动定时器，每5秒播报一次
            if self.is_processing:
                self.speech_timer.start(5000)  # 5000毫秒 = 5秒
        else:
            # 停止定时器
            self.speech_timer.stop()
    
    def toggle_processing(self):
        if not self.is_processing:
            # 检查视频捕获对象是否有效
            if not self.cap or not self.cap.isOpened():
                self.video_panel.set_status_message("视频流未就绪")
                return
                
            # 开始处理
            self.is_processing = True
            self.control_panel.update_start_button(True)
            self.timer.start(30)  # 30ms 刷新率
            
            # 如果自动播报已启用，开始定时播报
            if self.auto_speech_enabled:
                self.speech_timer.start(5000)  # 5000毫秒 = 5秒
        else:
            # 停止处理
            self.timer.stop()
            self.is_processing = False
            self.control_panel.update_start_button(False)
            
            # 停止定时播报，但保持自动播报状态
            self.speech_timer.stop()
    
    def _process_frame(self):
        if self.cap and self.is_processing:
            try:
                success, frame = self.cap.read()
                if not success:
                    self.video_panel.set_status_message("无法读取视频帧")
                    return
                
                # 使用检测器处理帧
                stats_frame, total_objects, class_counts = self.detector.process_frame(frame)
                
                # 显示处理后的帧和更新统计信息
                self.video_panel.display_frame(stats_frame)
                self.video_panel.update_stats(total_objects, class_counts)
                
            except Exception as e:
                self.video_panel.set_status_message(f"处理视频帧时发生错误: {str(e)}")
                if self.cap:
                    self.cap.release()
                self.toggle_processing()  # 停止处理

    def speak_results(self):
        '''语音播报检测结果'''
        if not self.tts_engine.is_available():
            from PySide6.QtWidgets import QMessageBox
            QMessageBox.warning(self, "语音引擎不可用", "请确保已安装pyttsx3库。\n"
                              "可以通过运行 'pip install pyttsx3'安装。")
            return
    
        # 构建要播报的文本
        if hasattr(self, 'detector') and hasattr(self.detector, 'unique_object_ids'):
            total_objects = len(self.detector.unique_object_ids)
        
            speak_text = f"区域内共检测到{total_objects}个物体。"
        
            # 添加各类别数量信息
            if hasattr(self.detector, 'class_counts') and self.detector.class_counts:
                for class_name, count in sorted(
                    self.detector.class_counts.items(), 
                    key=lambda x: x[1], 
                    reverse=True
                )[:3]:  # 只报告前三个最多的类别
                    if count > 0:
                        speak_text += f"其中{class_name}{count}个。"
        
            # 播放语音
            self.tts_engine.speak(speak_text)
            
    def change_valve_image(self, image_name):
        """更改蝶阀图片"""
        self.valve_panel.load_valve_image(image_name)
    
    def _handle_io_state_change(self, state):
        """处理PLC输入状态变化"""
        if state:
            self.change_valve_image("蝶阀开.png")
        else:
            self.change_valve_image("蝶阀关.png")

    def closeEvent(self, event):
        # 断开PLC连接
        if hasattr(self, 'plc_client'):
            self.plc_client.disconnect()
        # 程序关闭时释放资源
        if self.cap:
            self.cap.release()
        
        # 停止所有定时器
        self.timer.stop()
        self.speech_timer.stop()
        
        event.accept()

    def connect_raspberry_pi(self):
        """连接树莓派并获取视频流"""
        dialog = IPInputDialog(self)
        if dialog.exec():
            ip_address = dialog.get_ip_address()
            port = dialog.get_port()
            
            if ip_address and port:
                try:
                    # 使用HTTP流地址
                    http_url = f"http://{ip_address}:{port}/video_feed"
                    
                    # 设置OpenCV的FFMPEG参数
                    self.cap = cv2.VideoCapture(http_url, cv2.CAP_FFMPEG)
                    
                    # 设置FFMPEG参数
                    self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 3)
                    # 设置超时时间（毫秒）
                    self.cap.set(cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 10000)  # 10秒连接超时
                    self.cap.set(cv2.CAP_PROP_READ_TIMEOUT_MSEC, 10000)  # 10秒读取超时
                    
                    # 尝试读取一帧来验证连接
                    ret, frame = self.cap.read()
                    if ret:
                        self.video_path = http_url
                        self.control_panel.start_button.setEnabled(True)
                        self.video_panel.set_status_message(f"已连接到视频服务器: {ip_address}:{port}")
                        # 初始化检测器
                        self.detector.initialize()
                    else:
                        self.video_panel.set_status_message("无法读取视频流")
                        if self.cap:
                            self.cap.release()
                            self.cap = None
                except Exception as e:
                    self.video_panel.set_status_message(f"连接失败: {str(e)}")
                    if self.cap:
                        self.cap.release()
                        self.cap = None